/**
 * OSAmI: Open Source Ambient Intelligence
 * Copyright (C) 2010 Bull S.A.S.
 * Contact: osami-general@osami-commons.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $Id: IdentityDetailsOperation.java 379 2011-04-20 14:22:51Z osami.fr $
 * --------------------------------------------------------------------------
 */


package org.osami.gateway.display.internal.identity;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Instantiate;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.Requires;
import org.osami.gateway.display.internal.ServletPaths;
import org.osami.gateway.identity.Identity;
import org.osami.gateway.identity.IdentityManager;

/**
 * A {@code ListIdentitiesOperation} is ...
 *
 * @author Guillaume Sauthier
 */
@Component
@Provides
@Instantiate
public class IdentityDetailsOperation implements WebOperation {

    public static final String PATTERN = "/details";

    @Requires
    private IdentityManager manager;

    public String getRecognizedPattern() {
        return "/{id}/details";
    }

    public void execute(final HttpServletRequest request,
                        final HttpServletResponse response,
                        final Map<String, String> urlParameters)
            throws ServletException, IOException {

        PrintWriter writer = response.getWriter();

        String id = urlParameters.get("id");
        Identity identity = this.manager.getIdentity(id);

        if (identity == null) {
            throw new ServletException("Unknown Identity : " + id);
        }

        writer.println("<html lang='en'>");

        // HTML Head
        // ---------------------------------------------------
        writer.println("<head>");
        writer.println("<title>Identity Details</title>");
        writer.println("<link href=\"/resource/css/designSensor.css\" rel=\"stylesheet\" type=\"text/css\" />");
        writer.println("</head>");

        // HTML Body
        // ---------------------------------------------------
        writer.println("<body>");

        printPageTitle(writer, identity);
        printIdentityDetailsTable(writer, identity);

        writer.println("<hr />");
        printBackButton(writer);
        printCopyButton(writer, identity);
        writer.println("<a href=\"" + IdentitiesServlet.IDENTITY + "\">Go back to main identity page</a><br />");
        writer.println("<a href=\"" + ServletPaths.INDEX + "\">Go back to main page</a>\n");

        writer.println("</body>");

        writer.println("</html>");
    }

    private void printPageTitle(PrintWriter writer, Identity identity) {
        writer.println("<h1>Identity details for " + identity.getIdentityID() + "</h1><hr/>\n");
    }

    private void printBackButton(PrintWriter writer) {
        String action = IdentitiesServlet.IDENTITY + ListIdentitiesOperation.PATTERN;
        writer.println("<form method='GET' action='" + action + "'>");
        writer.println("  <input type='submit' value='List Identities' />");
        writer.println("</form>");
    }

    private void printCopyButton(PrintWriter writer, Identity identity) {
        writer.println("<a href=\"" + IdentitiesServlet.IDENTITY + CreateIdentityOperation.PATTERN + "?parent-id=" + identity.getIdentityID() + "\">Create identity based on this one</a><br /><br />");
        // For some reason, this doesn't yield the intended effect.
        /*writer.println("<form method='GET' action='" + action + "'>");
        writer.println("  <input type='submit' value='Create identity based on this one' />");
        writer.println("</form>");*/
    }

    private void printIdentityDetailsTable(PrintWriter writer, Identity identity) {
        writer.println("<table width='100%' border='1'>");

        // Print table body
        writer.println("<tbody>");

        // title
        String message = "Identity (" + identity.getIdentityID() + ")";
        printTransitionalHeader(writer, message);

        // Special attributes
        // ---- name ----
        writer.println("<tr>");
        writer.println("<td>name</td>");
        writer.println("  <td>");
        printPropertyValueChangeForm(writer, identity, Identity.FRIENDLY_NAME, identity.getName(), false);
        writer.println("  </td>");
        writer.println("</tr>");
        // ---- bound ----
        writer.println("<tr>");
        writer.println("<td>bound</td>");
        writer.println("  <td>");
        printPropertyValueChangeForm(writer, identity, "bound", identity.getBoundIdentifier(), true);
        writer.println("  </td>");
        writer.println("</tr>");

        // All other attributes of this Identity (separated from parent properties)
        Identity traversed = identity;
        do {

            if (!identity.equals(traversed)) {
                // print a mini header to separate children and parents
                String transition = "Parent Identity (" + traversed.getIdentityID() + ")";
                printTransitionalHeader(writer, transition);
            }

            // Print each properties in a row
            Map<String, Object> properties = traversed.getProperties();
            for (Map.Entry<String, Object> entry : properties.entrySet()) {
                if (!entry.getKey().equals(Identity.FRIENDLY_NAME)) {
                    // Do not print friendly name twice
                    printIdentityPropertyCell(writer, traversed, entry);
                }
            }
            // Add an additional row with free name and value
            printAdditionalPropertyForm(writer, traversed);

            traversed = traversed.getParent();
        } while (traversed != null);

        writer.println("</tbody>");
        writer.println("</table>");
    }

    private void printAdditionalPropertyForm(PrintWriter writer, Identity identity) {

        String action = IdentitiesServlet.IDENTITY + "/" + identity.getIdentityID() + AddPropertyIdentityOperation.PATTERN;

        writer.println("<tr>");
        writer.println("<form method='GET' action='" + action + "'>");

        writer.println("  <td>");
        writer.println("  <input name='" + AddPropertyIdentityOperation.NAME + "' type='text' size='40' />");
        writer.println("  </td>");

        writer.println("  <td>");
        writer.println("  <input name='" + AddPropertyIdentityOperation.VALUE + "' type='text' size='40' />");
        writer.println("  <input type='submit' value='Add' />");
        writer.println("  </td>");

        writer.println("</form>");
        writer.println("</tr>");
    }

    private void printPropertyValueChangeForm(final PrintWriter writer,
                                              final Identity identity,
                                              final String name,
                                              final Object value,
                                              final boolean disabled) {
        String action = IdentitiesServlet.IDENTITY + "/" + identity.getIdentityID()
                + ChangePropertyIdentityOperation.PATTERN + "/" + name;
        writer.println("<form method='GET' action='" + action + "'>");

        String disabledAttribute = "";
        if (disabled) {
            disabledAttribute = "disabled='true' ";
        }
        writer.println("  <input name='" + ChangePropertyIdentityOperation.NEW_VALUE + "' " + disabledAttribute
                + "type='text' size='40' value='" + value + "' />");
        writer.println("  <input type='submit' value='Change' " + disabledAttribute + "/>");
        writer.println("</form>");

    }

    private void printTransitionalHeader(PrintWriter writer, String message) {
        writer.println("<tr>");
        writer.println("<td colspan='2' align='center'><b>");
        writer.println(message);
        writer.println("</b></td>");
        writer.println("</tr>");
    }

    private void printIdentityPropertyCell(PrintWriter writer, Identity identity, Map.Entry<String, Object> entry) {
        writer.println("<tr>");
        writer.println("<td>" + entry.getKey() + "</td>");
        writer.println("  <td>");
        printPropertyValueChangeForm(writer, identity, entry.getKey(), entry.getValue(), false);
        writer.println("  </td>");
        writer.println("</tr>");
    }

}
